﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using iNet.Win32;

namespace iNet.Windows
{
	/// <summary>
	/// 視窗基底類別。
	/// </summary>
	public class Window : System.Windows.Window
	{
		#region 相依性屬性
		/// <summary>
		/// 識別 IsIconVisible 相依性屬性。
		/// </summary>
		public static readonly DependencyProperty IsIconVisibleProperty;
		#endregion
		#region 型別建構子
		static Window()
		{
			IsIconVisibleProperty = DependencyProperty.Register("IsIconVisible", typeof(bool), typeof(Window), new PropertyMetadata(true, OnIsIconVisibleChanged));
		}
		#endregion
		#region 欄位
		IntPtr _Handle;
		bool _IsClosed;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 Window 執行個體。
		/// </summary>
		public Window()
		{ }
		#endregion
		#region Handle
		/// <summary>
		/// 取得視窗的 Handle (HWND)。
		/// </summary>
		public IntPtr Handle
		{
			get
			{
				if (_Handle == IntPtr.Zero && !_IsClosed)
					_Handle = new WindowInteropHelper(this).EnsureHandle();
				return _Handle;
			}
		}
		#endregion
		#region IsIconVisible
		/// <summary>
		/// 取得或設定是否顯示視窗圖示，預設值為 True。
		/// </summary>
		public bool IsIconVisible
		{
			get
			{
				return (bool)this.GetValue(IsIconVisibleProperty);
			}
			set
			{
				this.SetValue(IsIconVisibleProperty, value);
			}
		}
		#endregion
		#region OnClosed
		/// <summary>
		/// 引發 Closed 事件。
		/// </summary>
		/// <param name="e">事件資料。</param>
		protected override void OnClosed(EventArgs e)
		{
			//呼叫基底
			base.OnClosed(e);

			//重設欄位
			_IsClosed = true;
			_Handle = IntPtr.Zero;
		}
		#endregion
		#region OnIsIconVisibleChanged
		static void OnIsIconVisibleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
		{
			(obj as Window).OnIsIconVisibleChanged((bool)e.NewValue);
		}
		void OnIsIconVisibleChanged(bool isVisible)
		{
			if (_Handle != IntPtr.Zero)
			{
				WS_EX styles = (WS_EX)User32.GetWindowLong(_Handle, GWL.EXSTYLE);
				if (isVisible)
					styles &= ~WS_EX.DLGMODALFRAME;
				else
					styles |= WS_EX.DLGMODALFRAME;
				User32.SetWindowLong(_Handle, GWL.EXSTYLE, styles);
			}
		}
		#endregion
		#region OnSourceInitialized
		/// <summary>
		/// 引發 SourceInitialized 事件。
		/// </summary>
		/// <param name="e">事件資料。</param>
		protected override void OnSourceInitialized(EventArgs e)
		{
			//取得 HWND
			if (_Handle == IntPtr.Zero)
				_Handle = new WindowInteropHelper(this).Handle;

			//連結訊息處理函式
			HwndSource.FromHwnd(_Handle).AddHook(this.WndProc);

			//更新圖示
			this.OnIsIconVisibleChanged((bool)this.GetValue(IsIconVisibleProperty));

			//呼叫基底
			base.OnSourceInitialized(e);
		}
		#endregion
		#region WndProc
		/// <summary>
		/// 處理視窗訊息。
		/// </summary>
		/// <param name="msg">訊息識別碼。</param>
		/// <param name="wParam">訊息參數。</param>
		/// <param name="lParam">訊息參數。</param>
		/// <param name="handled">是否處理此訊息。</param>
		/// <returns>訊息處理結果。</returns>
		protected virtual IntPtr WndProc(int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
		{
			handled = false;
			return IntPtr.Zero;
		}
		private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
		{
			if (hWnd == this.Handle)
				return this.WndProc(msg, wParam, lParam, ref handled);
			return IntPtr.Zero;
		}
		#endregion
	}
}
